
// Comparison of bounded buffers based on different containers.

// Copyright (c) 2003-2008 Jan Gaspar

// Use, modification, and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef _C_PRODUCER_HPP_
#define _C_PRODUCER_HPP_

#define BOOST_CB_DISABLE_DEBUG

#include <boost/circular_buffer.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition.hpp>
#include <boost/thread/thread.hpp>
#include <boost/progress.hpp>
#include <boost/bind.hpp>
#include <deque>
#include <list>
#include <string>
#include <iostream>

template <class T>
class bounded_buffer {
public:

    /// This defines the data type of the buffer, to be used on other non-member functions
    typedef T value_type;
    typedef typename boost::circular_buffer<T> ::size_type size_type;

    explicit bounded_buffer(size_type capacity) : m_container(capacity),m_unread(0),m_cancel(0) {}
    ~bounded_buffer()
    {
	printf("bounded_buffer destructor\n");
	cancel();
    }
    bool push_front(const T& item) {
        boost::mutex::scoped_lock lock(m_mutex);
        m_not_full.wait(lock, boost::bind(&bounded_buffer<T>::_is_not_full, this));
	if (m_cancel)
	{
	    lock.unlock();
	    return false;
	}
        m_container.push_front(item);
        ++m_unread;
        lock.unlock();
        m_not_empty.notify_one();
	return true;
    }

    void pop_back(T* pItem) {
        boost::mutex::scoped_lock lock(m_mutex);
        m_not_empty.wait(lock, boost::bind(&bounded_buffer<T>::_is_not_empty, this));
	if (m_cancel)
	{
	    lock.unlock();
	    return;
	}
        *pItem = m_container[--m_unread];
        lock.unlock();
        m_not_full.notify_one();
    }

    void cancel(void)
    {
	m_cancel=true;
	m_not_full.notify_one();
	m_not_empty.notify_one();
    }

    void activate(void)
    {
	m_cancel = false;
    }

    bool is_not_empty() const { return m_unread > 0 ; }
    bool is_not_full() const { return m_unread < m_container.capacity(); }

private:

    bool _is_not_empty() const { return m_unread > 0 || m_cancel; }
    bool _is_not_full() const { return m_unread < m_container.capacity() || m_cancel; }

    boost::circular_buffer<T> m_container;
    typename boost::circular_buffer<T>::size_type m_unread;
    boost::mutex m_mutex;
    boost::condition m_not_empty;
    boost::condition m_not_full;
    bool m_cancel;

    bounded_buffer(const bounded_buffer<T>&);              // Disabled copy constructor
    bounded_buffer& operator = (const bounded_buffer<T>&); // Disabled assign operator
};

template <class T>
class CProducer {
protected:
    bounded_buffer<T> m_container;
    T m_item;
    boost::thread *m_thread;
    bool m_quit;
public:

    CProducer(typename bounded_buffer<T>::size_type capacity)
	: m_container(capacity) 
    {
	m_quit=0;
    }
    ~CProducer()
    {
	printf("CProducer destructor\n");
	stop();
    }
    virtual bool start(void)
    {
	m_quit=0;
	//start the CProducer thread
	m_thread = new boost::thread (boost::ref(*this));
	return m_thread != NULL;
    }
    virtual void operator()()//=0 ;
    {
	T a();
	//thread
        while (!m_quit)
	{
	    //calll();
            m_container.push_front(T());
	}
    }
    //virtual void calll()=0;
    virtual void stop()
    {
	m_quit = true;
	m_container.cancel();
	m_thread->join();
	m_container.activate();

    }
    virtual T consumer() 
    {
	T item;
	m_container.pop_back(&item);
	return item;
    }
    virtual inline bool quit() {return m_quit;}
};



/*
int main()
{
    int n;
    boost::progress_timer progress;    

    //CProducer<int> Producer(100);
    readthread Producer (100);
    Producer.start();
    std::cout << "consumer created-------------------\n";

    for (unsigned long i = 0L; i < TOTAL_ELEMENTS+3; ++i)
	n=Producer.consumer();

    printf("working ....\n");
    
    usleep(20000);

    Producer.stop();

    printf("program finish with %d ----------------------------\n", n);

    return 0;
}
*/

#endif
